package com.common.frame.base

import android.app.Activity
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.ApplicationInfo
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import android.util.Log
import android.view.View
import androidx.annotation.ColorInt
import androidx.appcompat.app.AppCompatActivity
import androidx.core.text.inSpans
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentFactory
import com.common.frame.extension.getColor
import com.common.frame.utils.Utils
import com.common.frame.widget.ClickableSpan
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.hjq.toast.ToastUtils
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject


fun Activity.navigateTo(cls: Class<*>, bundle: Bundle? = null) {
    startActivity(Intent(this, cls).apply {
        bundle?.let {
            putExtras(bundle)
        }
    })
}

fun Fragment.navigateTo(cls: Class<*>, bundle: Bundle? = null) {
    startActivity(Intent(context, cls).apply {
        bundle?.let {
            putExtras(bundle)
        }
    })
}

fun Activity.navigateForResult(requestCode: Int, cls: Class<*>, bundle: Bundle? = null) {
    startActivityForResult(Intent(this, cls).apply {
        bundle?.let {
            putExtras(bundle)
        }
    }, requestCode)
}

fun Fragment.navigateForResult(requestCode: Int, cls: Class<*>, bundle: Bundle? = null) {
    startActivityForResult(Intent(context, cls).apply {
        bundle?.let {
            putExtras(bundle)
        }
    }, requestCode)
}

fun Activity.finishWithResult(resultCode: Int = Activity.RESULT_OK, intent: Intent? = null) {
    intent?.let {
        setResult(resultCode, it)
    } ?: setResult(resultCode)
    finish()
}

inline fun <reified T : Fragment> Context.newInstanceFragment(): T {
    val args = Bundle()
    val className = T::class.java.name;
    val clazz = FragmentFactory.loadFragmentClass(
        classLoader, className
    )
    val f = clazz.getConstructor().newInstance()
    args.classLoader = f.javaClass.classLoader
    f.arguments = args
    return f as T
}

inline fun <reified T : Fragment> Context.newInstanceFragment(args: Bundle?): T {
    val className = T::class.java.name;
    val clazz = FragmentFactory.loadFragmentClass(
        classLoader, className
    )
    val f = clazz.getConstructor().newInstance()
    if (args != null) {
        args.classLoader = f.javaClass.classLoader
        f.arguments = args
    }
    return f as T
}

inline fun <reified T : Fragment> Context.newInstanceFragment(vararg pair: Pair<String, String>): T {
    val args = Bundle()
    for (arg in pair) {
        args.putString(arg.first, arg.second)
    }
    val className = T::class.java.name;
    val clazz = FragmentFactory.loadFragmentClass(
        classLoader, className
    )
    val f = clazz.getConstructor().newInstance()
    args.classLoader = f.javaClass.classLoader
    f.arguments = args
    return f as T
}

fun <T> isNotEmpty(list: List<T>?): Boolean {
    return list != null && list.isNotEmpty()
}

fun getColorInt(s: String): Int {
    return Color.parseColor(s)
}


fun Activity.openSetting(code: Int = 0) {
    val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
    intent.data = Uri.fromParts("package", packageName, null)
    startActivityForResult(intent, code)
}

fun isLandscape(flag: Int): Boolean {
    return flag == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
            flag == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
}


val isDebug: Boolean
    get() {
        return try {
            val info = Utils.app.applicationInfo
            info.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0
        } catch (e: Exception) {
            false
        }
    }


fun formatJson(json: String, indentSpaces: Int = 4): String? {
    try {
        var i = 0
        val len = json.length
        while (i < len) {
            val c = json[i]
            if (c == '{') {
                return JSONObject(json).toString(indentSpaces)
            } else if (c == '[') {
                return JSONArray(json).toString(indentSpaces)
            } else if (!Character.isWhitespace(c)) {
                return json
            }
            i++
        }
    } catch (e: JSONException) {
        e.printStackTrace()
    }
    return json
}

fun Context.openApp(packageName: String) {
    startActivity(packageManager.getLaunchIntentForPackage(packageName))
}

inline fun <reified T> String.jsonToList(): ArrayList<T> =
    Gson().fromJson(this, object : TypeToken<MutableList<T>>() {}.type)

inline fun <reified K, V> String.jsonToMap(): HashMap<K, V> =
    Gson().fromJson(this, object : TypeToken<HashMap<K, V>>() {}.type)

fun Any.toJson(): String = Gson().toJson(this)

fun isDoubleClick(v: View, ignoreTime: Int = 1000): Boolean {
    val tag = v.getTag(v.id)
    val beforeTime = if (tag != null) tag as Long else 0
    val currentTimeMillis = System.currentTimeMillis()
    return if (currentTimeMillis - beforeTime >= ignoreTime) {
        v.setTag(v.id, currentTimeMillis)
        false
    } else {
        true
    }
}

fun Context.backToDesktop() {
    val i = Intent(Intent.ACTION_MAIN)
    i.addCategory(Intent.CATEGORY_HOME)
    startActivity(i)
}

fun Context.openExternalBrowser(url: String) {
    val intent = Intent()
    intent.action = "android.intent.action.VIEW"
    intent.data = Uri.parse(url)
    startActivity(intent)
}

fun String.copy() {
    val cm = Utils.app.getSystemService(AppCompatActivity.CLIPBOARD_SERVICE) as ClipboardManager
    cm.setPrimaryClip(ClipData.newPlainText("Label", this))
    ToastUtils.show("复制成功")
}

fun Context.getSimpleName(): String {
    return this::class.java.simpleName
}

fun String.debugLog(tag: String = "@@") {
    Log.d(tag, this)
}

fun SpannableStringBuilder.appendClickable(
    text: CharSequence?,
    color: Int? = null,
    isUnderLineText: Boolean = false,
    onclick: (View) -> Unit
): SpannableStringBuilder {
    return inSpans(ClickableSpan(color, isUnderLineText, onclick)) {
        append(text)
    }
}

fun SpannableStringBuilder.appendForegroundColor(
    text: CharSequence?,
    color: Int
): SpannableStringBuilder {
    return inSpans(ForegroundColorSpan(color.getColor())) {
        append(text)
    }
}